#ifdef ARMCLANG_COMPILER
__asm(".global __use_no_semihosting\n\t");
__asm(".global __use_utf8_ctype\n\t");
__asm(".global __use_two_region_memory\n\t");
__asm(".global __use_realtime_heap\n\t");
__asm(".global __use_utf8_ctype\n\t");
#else
#pragma import(__use_no_semihosting)
#pragma import(__use_utf8_ctype)
#pragma import(__use_two_region_memory)
#pragma import(__use_realtime_heap)
#pragma import(__use_utf8_ctype)
#endif

#include "cpu.h"
#include "interrupt.h"
#include "led.h"
#include "mmu.h"
#include "uart.h"
#include <locale.h>
#include <rt_sys.h>
#include <string.h>

// C库并未向外提供该函数，但是可以重写此函数以便在进入的main函数之前进行
// 相关的操作，例如硬件的初始化，MMU的开启
void _platform_post_lib_init(void) {
  //设置本地字符处理方式
  setlocale(LC_CTYPE, "utf8");
  led_init();
  uart_initModule();
  //初始化中断系统
  interrupt_initISR();
  //初始化MMU,
  mmu_init();
}

  // direct semihosting depended functions
  //  1. __user_initial_stackheap() 初始化堆栈
  //  2. _sys_exit() 不能退出
  //  3. _ttywrch() 向控制台输出一个字符
  //  4. sys_command_string() 获取命令行字符串
  //  5. _sys_close()
  //  6. _sys_iserror()
  //  7. _sys_istty()
  //  8. _sys_flen()
  //  9. _sys_open()
  //  10. _sys_read()
  //  11. _sys_seek()
  //  12. _sys_write()
  //  13. _sys_tmpnam()
  //  14. clock()
  //  15. _clock_init()
  //  16. remove()
  //  17. rename()
  //  18. system()
  //  19. time()

  // Indirect semihosting C library function dependencies

  //  1. __user_setup_stackheap()
  //  2. __raise()
  //  3. __default_signal_handler()
  //  4. __Heap_Initialize()
  //  5. ferror(), fputc(), __stdout
  //  6. __backspace(), fgetc(), __stdin
  //  7. fwrite(), fputs(), puts(), fread(), fgets(), gets(), ferror()

  // TODO:重写其他依赖semihosting的函数
  //使用串口或者屏幕作为标准输出设备
  //实现low-level的输入输出函数，缓冲区，流控制

#define STDIN 1
#define STDOUT 2
#define STDERR 3

#define SYS_IO_PREFIX(funcName) $Sub$$##funcName

extern void _sys_exit(int return_code);
extern char *_sys_command_string(char *cmd, int len);
extern void _ttywrch(int ch);

void SYS_IO_PREFIX(_sys_exit)(int return_code) {
  //不能退出
  while (1) {
  };
}

//
char *SYS_IO_PREFIX(_sys_command_string)(char *cmd, int len) {
  return (char *)(0);
}

void SYS_IO_PREFIX(_ttywrch)(int ch) {
  // do nothing
}

const char SYS_IO_PREFIX(__stdin_name)[] = "STDIN";
const char SYS_IO_PREFIX(__stdout_name)[] = "STDOUT";
const char SYS_IO_PREFIX(__stderr_name)[] = "STDERR";

FILEHANDLE SYS_IO_PREFIX(_sys_open)(const char *name, int openmode) {
  if (strcmp(name, __stdin_name) == 0)
    return (FILEHANDLE)STDIN;
  if (strcmp(name, __stdout_name) == 0)
    return (FILEHANDLE)STDOUT;
  if (strcmp(name, __stderr_name) == 0)
    return (FILEHANDLE)STDERR;
  return -1;
}

int SYS_IO_PREFIX(_sys_close)(FILEHANDLE fh) { return 0; }

int SYS_IO_PREFIX(_sys_seek)(FILEHANDLE fh, long pos) {
  if (fh <= STDERR)
    return -1;
  //其他情况处理
  return -1;
}

int SYS_IO_PREFIX(_sys_read)(FILEHANDLE fh, unsigned char *buf, unsigned len,
                             int mode) {
  if (fh == STDIN) {
    // TODO
    return 0;
  }
  if (fh == STDOUT || fh == STDERR)
    return -1;
  return -1;
}

int SYS_IO_PREFIX(_sys_write)(FILEHANDLE fh, const unsigned char *buf,
                              unsigned len, int mode) {
  if (fh == STDOUT || fh == STDERR) {
    return 0;
  }
  if (fh == STDIN)
    return -1;
  return -1;
}

void SYS_IO_PREFIX(_sys_tmpnam)(char *name, int fileno, unsigned maxlength) {
  // do nothing
}

long SYS_IO_PREFIX(_sys_flen)(FILEHANDLE fh) { return 0; }

int SYS_IO_PREFIX(_sys_istty)(FILEHANDLE fh) { return 0; }

int SYS_IO_PREFIX(system)(const char *string) { return 0; }

int SYS_IO_PREFIX(remove)(const char *filename) { return -1; }

int SYS_IO_PREFIX(rename)(const char *old, const char *new) { return 1; }
